package com.psp.stockprice.service.impl;

import java.util.*;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import com.psp.stock.domain.Stock;
import com.psp.stockprice.vo.CandleChartVO;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.uuid.IdUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import com.psp.stockprice.mapper.StockPriceMapper;
import com.psp.stockprice.domain.StockPrice;
import com.psp.stockprice.service.IStockPriceService;

import javax.annotation.Resource;

/**
 * 股票每日价格Service业务层处理
 *
 * @author ruoyi
 */
@Service
public class StockPriceServiceImpl implements IStockPriceService {

    private static final Logger log = LoggerFactory.getLogger(StockPriceServiceImpl.class);

    @Resource
    private StockPriceMapper stockPriceMapper;

    /**
     * 查询股票每日价格
     *
     * @param id 股票每日价格主键
     * @return 股票每日价格
     */
    @Override
    public StockPrice selectStockPriceById(String id) {
        return stockPriceMapper.selectStockPriceById(id);
    }

    /**
     * 查询股票每日价格列表
     *
     * @param stockPrice 股票每日价格
     * @return 股票每日价格
     */
    @Override
    public List<StockPrice> selectStockPriceList(StockPrice stockPrice) {
        return stockPriceMapper.selectStockPriceList(stockPrice);
    }

    /**
     * 获取最近的两条记录
     */
    @Override
    public List<StockPrice> selectRecentTwoRecord(String stockCode) {
        return stockPriceMapper.selectRecentTwoRecord(stockCode);
    }

    /**
     * 查询n天的交易日期
     *
     * @param days 查询天数
     * @return 交易日期
     */
    @Override
    public List<Map<String, Object>> selectStockTradeStartAndEndDate(int days) {
        return stockPriceMapper.selectStockTradeStartAndEndDate(days);
    }

    /**
     * 查询一段时间内的股票价格
     */
    @Override
    public List<StockPrice> selectStockPriceByStartAndEndDate(Date startDate, Date endDate) {
        return stockPriceMapper.selectStockPriceByStartAndEndDate(startDate, endDate);
    }

    /**
     * 查询某股票的一段时间内的股票价格
     */
    @Override
    public List<StockPrice> selectStockPriceByStartAndEndDate(String stockCode, Date startTime, Date endTime) {
        return stockPriceMapper.selectStockPriceByStartAndEndDateAndStockCode(stockCode, startTime, endTime);
    }

    /**
     * 查询是否存在某天的股票价格
     *
     * @param stockCode 股票编码
     * @param tradeDate 交易日期
     */
    @Override
    public Long selectByStockCodeAndTradeDate(String stockCode, Date tradeDate) {
        StockPrice stockPrice = stockPriceMapper.selectByStockCodeAndTradeDate(stockCode, tradeDate);
        return stockPrice == null ? null : stockPrice.getId();
    }

    /**
     * 获取某股票的历史价格
     *
     * @param stockCode 股票编码
     * @return 股票的历史价格
     */
    @Override
    public CandleChartVO getHistoryPriceByStockCode(String stockCode) {
        List<StockPrice> stockPriceList = stockPriceMapper.getHistoryPriceByStockCode(stockCode);
        CandleChartVO result = new CandleChartVO();
        List<String> date = new ArrayList<>();
        List<List<Float>> price = new ArrayList<>();
        if (stockPriceList != null && stockPriceList.size() > 0) {
            stockPriceList.forEach(n -> {
                List<Float> p = new ArrayList<>(8);
                date.add(DateUtil.format(n.getTradeDate(), "yyyy/MM/dd"));
                p.add(NumberUtil.round(n.getOpenPrice(), 2).floatValue());
                p.add(NumberUtil.round(n.getClosePrice(), 2).floatValue());
                p.add(NumberUtil.round(n.getLowest(), 2).floatValue());
                p.add(NumberUtil.round(n.getHighest(), 2).floatValue());
                p.add(n.getVolume() != null ? NumberUtil.round(n.getVolume(), 0).floatValue() : 0);
                price.add(p);
            });
        }
        result.setDate(date);
        result.setPrice(price);
        return result;
    }

    /**
     * 新增股票每日价格
     *
     * @param stockPrice 股票每日价格
     * @return 结果
     */
    @Override
    public int insertStockPrice(StockPrice stockPrice) {
        return stockPriceMapper.insertStockPrice(stockPrice);
    }

    /**
     * 修改股票每日价格
     *
     * @param stockPrice 股票每日价格
     * @return 结果
     */
    @Override
    public int updateStockPrice(StockPrice stockPrice) {
        return stockPriceMapper.updateStockPrice(stockPrice);
    }

    /**
     * 批量删除股票每日价格
     *
     * @param ids 需要删除的股票每日价格主键
     * @return 结果
     */
    @Override
    public int deleteStockPriceByIds(String[] ids) {
        return stockPriceMapper.deleteStockPriceByIds(ids);
    }

    /**
     * 删除股票每日价格信息
     *
     * @param id 股票每日价格主键
     * @return 结果
     */
    @Override
    public int deleteStockPriceById(String id) {
        return stockPriceMapper.deleteStockPriceById(id);
    }

    /**
     * 根据股票交易日期删除股票价格
     *
     * @param tradeDate 股票交易日期
     */
    @Override
    public void deleteStockPriceByTradeDate(Date tradeDate) {
        stockPriceMapper.deleteStockPriceByTradeDate(tradeDate);
    }

    /**
     * 更新股票的历史股价,股价必须有日期且从小到大连续
     */
    @Override
    public void insertOrUpdateStockHistoryPrice(Stock stock, List<List<String>> price) {

        if (price == null) {
            return;
        }

        log.debug("删除股票时间范围内的历史价格");
        Date minDate = null;
        Date maxDate = null;
        if (price.size() > 0) {
            String minDateStr = price.get(0).get(0);
            String maxDateStr = price.get(price.size() - 1).get(0);
            minDate = DateUtil.parseDate(minDateStr);
            maxDate = DateUtil.parseDate(maxDateStr);
        }

        int deleteCount = stockPriceMapper.deleteStockPriceByDate(stock.getStockCode(), minDate, maxDate);
        log.debug("删除{}条股票历史价格数据", deleteCount);

        log.debug("插入时间范围内的历史价格");
        List<StockPrice> addList = new ArrayList<>(2000);
        price.forEach(n -> {
            StockPrice item = new StockPrice();
            item.setStockCode(stock.getStockCode());
            item.setTradeDate(DateUtil.parse(n.get(0)));
            item.setOpenPrice(Double.valueOf(n.get(1)));
            item.setClosePrice(Double.valueOf(n.get(2)));
            item.setHighest(Double.valueOf(n.get(3)));
            item.setLowest(Double.valueOf(n.get(4)));
            item.setVolume(NumberUtil.isDouble(n.get(5)) ? Double.parseDouble(n.get(5)) : 0L);
            addList.add(item);
        });
        stockPriceMapper.batchInsertStockPrice(addList);
    }
}
